/*
 * RTSAI - Real-Time Strategy engine for AI research
 * Copyright(C) 2006 DIMAp-UFRN, licensed under LGPL
 *
 * Pool allocator header ( Pool.h )
 * Author: Diogo Leite Reboucas
 */

#ifndef POOL_H_
#define POOL_H_

// INCLUDES -------------------------------------------------------------------
#include <vector>
#include <stack>

using std :: vector;
using std :: stack;

template < class T >
class PoolIterator
{
    public:
        PoolIterator ( vector < T > *v ) : pool ( v )
        {
            current_element = NULL;
            if ( pool ) // if this iterator was not constructed by the mehotd end()
            {           // then search for the first valid element
                for ( unsigned int i = 0 ; i < pool->size() ; i++ )
                {
                    // if is valid entity
                    if ( (*pool)[i].get_id() != -1 )
                    {
                        this->current_element = &(*pool)[i];
                        this->last_index = i;
                        break;
                    }
                }
            }
        }

        // pre increment
        PoolIterator < T > &operator++ ()
        {
            current_element = NULL;

            for ( unsigned int i = last_index + 1 ; i < pool->size() ; i++ )
            {
                if ( (*pool)[i].get_id() != -1 )
                {
                    this->current_element = &(*pool)[i];
                    this->last_index = i;
                    break;
                }
            }

            return *this;
        }

        // post increment
        PoolIterator < T > operator++ ( int )
        {
            PoolIterator < T > temp = *this;

            current_element = NULL;

            for ( unsigned int i = last_index + 1 ; i < pool->size() ; i++ )
            {
                if ( (*pool)[i].get_id() != -1 )
                {
                    this->current_element = &(*pool)[i];
                    this->last_index = i;
                    break;
                }
            }

            return temp;
        }

        T& operator *()
        {
            return *current_element;
        }

        PoolIterator < T > &operator= ( const PoolIterator < T > &rhs )
        {
            this->current_element = rhs.current_element;
            this->pool = rhs.pool;
            this->last_index = rhs.last_index;
        }

        bool operator== ( const PoolIterator < T > &rhs )
        {
            return (this->current_element == rhs.current_element);
        }

        bool operator!= ( const PoolIterator < T > &rhs )
        {
            return (this->current_element != rhs.current_element);
        }

        ~PoolIterator < T > () { /* empty */ }

    private:

        vector < T > *pool;
        T *current_element;
        int last_index;
};

// CLASS ----------------------------------------------------------------------
/*! This class implements an automatic pool allocator that improving
 *  performance by controlling data
 */
template < class T >
class Pool
{
    // PUBLIC METHODS =========================================================
    public:
        // Constructor --------------------------------------------------------
        Pool ( const int &a = 20 );
        // Pool ( const Pool& copy );

        // int ----------------------------------------------------------------
        int get_size ();
        int get_pool_size ();

        // T ------------------------------------------------------------------
        T& create ();
        T& operator [] ( const int& );

        // void ---------------------------------------------------------------
        void destroy ( T& );
        void clear ();

        // Destructor ---------------------------------------------------------
        ~Pool();

    // PRIVATE METHODS ========================================================
    private:
        // void ---------------------------------------------------------------
        void update_ids ();

    // ATTRIBUTES =============================================================
    private:
        /// The pool
        vector < T > pool;
        /// A stack to store references of unused entities
        stack < int > st;
        /// Current used entities
        unsigned int size;

    public:
        typedef PoolIterator< T > iterator;
        iterator begin () { return PoolIterator < T > ( &pool ); }
        iterator end () { return PoolIterator < T > ( NULL ); }

}; // End of Pool class

#include "PoolT.cpp"

#endif // POOL_H_
